// 订阅器模型，负责发布和订阅
let Dep = {
    clientList: [],
    // 添加订阅者
    listen: function (key, fn) {
        // vue 源码中的写法，短路表达式
        (this.clientList[key] || (this.clientList[key] = [])).push(fn);
    },

    trigger: function () {
        // 类数组转数组，改变 this 指向
        let key = Array.prototype.shift.call(arguments);
        let fns = this.clientList[key];
        // 如果没有订阅名单，或者有订阅名单，但没有什么操作（如：注册了淘宝，但什么也没买）
        if (!fns || fns.length === 0) {
            return false;
        }
        for (let i = 0, fn; fn = fns[i++];) {
            fn.apply(this, arguments);
        }
    }
};

// 劫持方法
/*
    data: 将要监听的对象
    tag: 目标对象
    datakey: only one，唯一性
    selector: 选择器selector
*/

let dataHijack = function ({ data, tag, datakey, selector }) {
    let value = '';
    let el = document.getElementById(selector);
    // 数据劫持
    Object.defineProperty(data, datakey, {
        get: function () {
            console.log('取值');
            return value;
        },
        set: function (val) {
            console.log('设置值');
            value = val; // 使得在 get 中可以取到新的值
            // 通知订阅者
            Dep.trigger(tag, val);
        }
    });

    //  通知之前必须要订阅，添加订阅者
    Dep.listen(tag, function (text) {
        el.innerHTML = text;
    });
};